﻿using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.Http.Controllers;
using System.Web.Http.Description;
using System.Xml.XPath;

namespace Cypher.Core.Default
{
	public sealed class DefaultDocumentationProvider : IDocumentationProvider
	{
		#region Fields

		XPathNavigator _documentNavigator;

		private const string _methodExpression = "/doc/members/member[@name='M:{0}']";
		private static Regex nullableTypeNameRegex = new Regex(@"(.*\.Nullable)" + Regex.Escape("`1[[") + "([^,]*),.*");

		#endregion

		#region Contructor(s)

		public DefaultDocumentationProvider(string documentationPath = null)
		{
			if (documentationPath == null)
				return;

			this._documentNavigator = new XPathDocument(documentationPath).CreateNavigator();
		}

		#endregion

		#region Methods

		private XPathNavigator GetMemberNode(HttpActionDescriptor actionDescriptor)
		{
			//ReflectedHttpActionDescriptor reflectedActionDescriptor = actionDescriptor as ReflectedHttpActionDescriptor;
			//if (reflectedActionDescriptor != null)
			//{
			//	string selectExpression = string.Format(_methodExpression, GetMemberName(reflectedActionDescriptor.MethodInfo));
			//	XPathNavigator node = _documentNavigator.SelectSingleNode(selectExpression);
			//	if (node != null)
			//	{
			//		return node;
			//	}
			//}

			return null;
		}

		//public virtual string GetNickname(HttpActionDescriptor actionDescriptor)
		//{
		//	ReflectedHttpActionDescriptor reflectedActionDescriptor = actionDescriptor as ReflectedHttpActionDescriptor;
		//	if (reflectedActionDescriptor != null)
		//	{
		//		return reflectedActionDescriptor.MethodInfo.Name;
		//	}

		//	return "NicknameNotFound";
		//}


		#endregion

		#region IDocumentationProvider Members

		public string GetDocumentation(System.Web.Http.Controllers.HttpParameterDescriptor parameterDescriptor)
		{
			ReflectedHttpParameterDescriptor reflectedParameterDescriptor = parameterDescriptor as ReflectedHttpParameterDescriptor;
			if (reflectedParameterDescriptor != null)
			{
				XPathNavigator memberNode = this.GetMemberNode(reflectedParameterDescriptor.ActionDescriptor);
				if (memberNode != null)
				{
					string parameterName = reflectedParameterDescriptor.ParameterInfo.Name;
					XPathNavigator parameterNode = memberNode.SelectSingleNode(string.Format("param[@name='{0}']", parameterName));
					if (parameterNode != null)
					{
						return parameterNode.Value.Trim();
					}
				}
			}

			return "No Documentation Found.";
		}

		public string GetDocumentation(System.Web.Http.Controllers.HttpActionDescriptor actionDescriptor)
		{
			return null;
			//throw new NotImplementedException();
		}

		public string GetDocumentation(System.Web.Http.Controllers.HttpControllerDescriptor controllerDescriptor)
		{
			return null;
			//throw new NotImplementedException();
		}

		public string GetResponseDocumentation(System.Web.Http.Controllers.HttpActionDescriptor actionDescriptor)
		{
			ReflectedHttpActionDescriptor reflectedActionDescriptor = actionDescriptor as ReflectedHttpActionDescriptor;
			if (reflectedActionDescriptor != null)
			{
				if (reflectedActionDescriptor.MethodInfo.ReturnType.IsGenericType)
				{
					StringBuilder sb = new StringBuilder(reflectedActionDescriptor.MethodInfo.ReturnParameter.ParameterType.Name);
					sb.Append("<");
					Type[] types = reflectedActionDescriptor.MethodInfo.ReturnParameter.ParameterType.GetGenericArguments();
					for (int i = 0; i < types.Length; i++)
					{
						sb.Append(types[i].Name);
						if (i != (types.Length - 1)) sb.Append(", ");
					}
					sb.Append(">");
					return sb.Replace("`1", "").ToString();
				}
				else
					return reflectedActionDescriptor.MethodInfo.ReturnType.Name;
			}

			return "void";
		}

		#endregion
	}
}
